home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 6366 / 6366.xpi / chrome / firegestures.jar / content / firegestures / prefs.js < prev    next >
Text File  |  2009-11-17  |  19KB  |  594 lines

  1.  
  2. const Cc = Components.classes;
  3. const Ci = Components.interfaces;
  4. const Cr = Components.results;
  5.  
  6. const TYPE_CATEGORY = Ci.xdIGestureMapping.TYPE_CATEGORY;
  7. const TYPE_NORMAL   = Ci.xdIGestureMapping.TYPE_NORMAL;
  8. const TYPE_SCRIPT   = Ci.xdIGestureMapping.TYPE_SCRIPT;
  9.  
  10. const kTypeCol      = 0;
  11. const kNameCol      = 1;
  12. const kCommandCol   = 2;
  13. const kDirectionCol = 3;
  14. const kFlagsCol     = 4;
  15.  
  16. const kExtraArray1 = [
  17.     ["wheelGestureU",  "wheel-up"    ],
  18.     ["wheelGestureD",  "wheel-down"  ],
  19.     ["rockerGestureL", "rocker-left" ],
  20.     ["rockerGestureR", "rocker-right"],
  21. ];
  22.  
  23. const kExtraArray2 = [
  24.     ["keypressGestureC", "keypress-ctrl" ],
  25.     ["keypressGestureS", "keypress-shift"],
  26. ];
  27.  
  28. const FG_TYPE_ATTR = "_command-type";
  29. const PREFS_DOMAIN = "extensions.firegestures.";
  30. const DRAGDROP_FLAVOR = "text/x-moz-tree-index";
  31.  
  32. const APP_VERSION = parseFloat(Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).version);
  33.  
  34. var gMappingArray = [];
  35. var gMappingView = null;
  36. var gShouldCommit = false;
  37.  
  38.  
  39.  
  40. var PrefsUI = {
  41.  
  42.     _gestureSvc: null,
  43.  
  44.     _gestureMapping: null,
  45.  
  46.     get promptSvc() {
  47.         return Cc["@mozilla.org/embedcomp/prompt-service;1"].
  48.                getService(Ci.nsIPromptService);
  49.     },
  50.  
  51.     init: function() {
  52.         this._gestureSvc = Cc["@xuldev.org/firegestures/service;1"].getService(Ci.xdIGestureService);
  53.         if ("arguments" in window) {
  54.             this._gestureMapping = this._gestureSvc.getMapping(window.arguments[0]);
  55.             document.title = this._gestureMapping.name + " : " + document.title;
  56.             document.documentElement.setAttribute("windowtype", window.name);
  57.         }
  58.         else
  59.             this._gestureMapping = this._gestureSvc.getMappingForBrowser();
  60.         gMappingArray = this._gestureMapping.getMappingArray();
  61.         gMappingArray = gMappingArray.filter(function(item) {
  62.             var flags = item[kFlagsCol];
  63.             if (flags && flags.indexOf("hidden") >= 0)
  64.                 return false;
  65.             if (flags && /^min:firefox([\d\.]+)$/.test(flags) && parseFloat(RegExp.$1) > APP_VERSION)
  66.                 return false;
  67.             if (flags && /^max:firefox([\d\.]+)$/.test(flags) && parseFloat(RegExp.$1) < APP_VERSION)
  68.                 return false;
  69.             return /^[LRUD]*$/.test(item[kDirectionCol]);
  70.         });
  71.         var mappingTree = document.getElementById("mappingTree");
  72.         gMappingView = new CustomTreeView();
  73.         mappingTree.view = gMappingView;
  74.         this.updateCommands();
  75.         this.rebuildExtraMenus1();
  76.         this.rebuildExtraMenus2();
  77.         var elt = document.getElementById("getScripts");
  78.         if (elt) {
  79.             var refChild = document.documentElement.getButton("extra2");
  80.             refChild.parentNode.insertBefore(elt, refChild);
  81.         }
  82.         if (navigator.platform.indexOf("Mac") == 0) {
  83.             elt.style.margin = "10px";
  84.             setTimeout(function() { window.sizeToContent(); }, 0);
  85.         }
  86.     },
  87.  
  88.     done: function() {
  89.         if (gShouldCommit) {
  90.             for each (let [id, direction] in kExtraArray1) {
  91.                 var menuList = document.getElementById(id);
  92.                 var type = parseInt(menuList.selectedItem.getAttribute(FG_TYPE_ATTR), 10);
  93.                 gMappingArray.push([type, menuList.label, menuList.value, direction]);
  94.             }
  95.             for each (let [id, direction] in kExtraArray2) {
  96.                 var menuList = document.getElementById(id);
  97.                 gMappingArray.push([TYPE_NORMAL, menuList.label, menuList.value, direction]);
  98.             }
  99.             try {
  100.                 this._gestureMapping.saveUserMapping(gMappingArray);
  101.             }
  102.             catch(ex) {
  103.                 var msg = "An error occurred while saving gesture mappings.\n\n" + ex;
  104.                 this.promptSvc.alert(window, "FireGestures", msg);
  105.             }
  106.         }
  107.         this._gestureMapping = null;
  108.         this._gestureSvc = null;
  109.     },
  110.  
  111.     rebuildExtraMenus1: function() {
  112.         for each (let [id, direction] in kExtraArray1) {
  113.             var menuList = document.getElementById(id);
  114.             var commandName  = null;
  115.             var commandValue = null;
  116.             if (menuList.itemCount == 0) {
  117.                 var command = this._gestureMapping.getCommandForDirection(direction);
  118.                 if (command) {
  119.                     commandName  = command.name;
  120.                     commandValue = command.value;
  121.                 }
  122.             }
  123.             else {
  124.                 commandName  = menuList.selectedItem.label;
  125.                 commandValue = menuList.selectedItem.value;
  126.                 menuList.removeAllItems();
  127.             }
  128.             menuList.appendItem("...", "").setAttribute(FG_TYPE_ATTR, TYPE_NORMAL);
  129.             var selItem = null;
  130.             for each (let [type, name, command] in gMappingArray) {
  131.                 if (type == TYPE_CATEGORY) {
  132.                     var newItem = document.getElementById("separatorTemplate").cloneNode(true);
  133.                     newItem.id = null;
  134.                     newItem.firstChild.setAttribute("value", name);
  135.                     menuList.menupopup.appendChild(newItem);
  136.                 }
  137.                 else {
  138.                     var newItem = menuList.appendItem(name, command);
  139.                     newItem.setAttribute(FG_TYPE_ATTR, type);
  140.                     if ((commandName || commandValue) && !selItem) {
  141.                         if ((type == TYPE_NORMAL && command == commandValue) || 
  142.                             (type == TYPE_SCRIPT && name == commandName))
  143.                             selItem = newItem;
  144.                     }
  145.                 }
  146.             }
  147.             menuList.selectedItem = selItem || menuList.getItemAtIndex(0);
  148.         }
  149.     },
  150.  
  151.     rebuildExtraMenus2: function() {
  152.         for each (let [id, direction] in kExtraArray2) {
  153.             var menuList = document.getElementById(id);
  154.             var command = this._gestureMapping.getCommandForDirection(direction);
  155.             if (!command)
  156.                 continue;
  157.             var elts = menuList.getElementsByAttribute("value", command.value);
  158.             if (elts.length > 0)
  159.                 menuList.selectedItem = elts[0];
  160.         }
  161.     },
  162.  
  163.     updateGroupedUI: function(aGroupName) {
  164.         var pref = document.getElementById(aGroupName).getAttribute("preference");
  165.         var val = document.getElementById(pref).value;
  166.         var enable = false;
  167.         switch (typeof(val)) {
  168.             case "boolean": enable = val;
  169.             case "number" : enable = val != 0;
  170.             case "string" : enable = val != "0";
  171.         }
  172.         Array.forEach(document.getElementsByAttribute("group", aGroupName), function(elt) {
  173.             elt.disabled = !enable;
  174.             if (elt.localName == "colorpicker")
  175.                 elt.style.MozOpacity = enable ? "1" : "0.5";
  176.         });
  177.         if (aGroupName == "mouseTrail")
  178.             this.updateMouseTrailSample();
  179.         else if (aGroupName == "gestureTimeout")
  180.             return enable;
  181.     },
  182.  
  183.     updateTriggerButton: function() {
  184.         var button = document.getElementById("extensions.firegestures.trigger_button").value;
  185.         ["wheelUpLabel", "wheelDownLabel"].forEach(function(id) {
  186.             var label = document.getElementById(id);
  187.             label.value = label.getAttribute("value" + button);
  188.         });
  189.         window.sizeToContent();
  190.     },
  191.  
  192.     updateMouseTrailSample: function() {
  193.         var elt = document.getElementById("mouseTrailSample");
  194.         var size = document.getElementById(PREFS_DOMAIN + "mousetrail.size").value;
  195.         elt.style.borderWidth = size.toString() + "px";
  196.         elt.style.borderColor = document.getElementById(PREFS_DOMAIN + "mousetrail.color").value;
  197.         if (document.getElementById("extensions.firegestures.mousetrail").value)
  198.             elt.previousSibling.disabled = (size == 1);
  199.     },
  200.  
  201.     changeMouseTrailSize: function(aIncrement) {
  202.         var pref = document.getElementById(PREFS_DOMAIN + "mousetrail.size");
  203.         pref.value = pref.value + aIncrement > 0 ? pref.value + aIncrement : 1;
  204.         this.updateMouseTrailSample();
  205.     },
  206.  
  207.     generateMappingsMenu: function(event) {
  208.         var menuPopup = event.target;
  209.         if (menuPopup.hasAttribute("_generated"))
  210.             return;
  211.         menuPopup.setAttribute("_generated", "true");
  212.         for each (let { id: id, name: name } in this._gestureSvc.getMappingsInfo()) {
  213.             var menuItem = document.createElement("menuitem");
  214.             menuItem.setAttribute("id", id);
  215.             menuItem.setAttribute("label", name);
  216.             menuPopup.appendChild(menuItem);
  217.         }
  218.     },
  219.  
  220.     backupMappings: function(aMenuItem) {
  221.         var dbConn = this._gestureSvc.getDBConnection(false);
  222.         if (!dbConn)
  223.             return;
  224.         var filePicker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
  225.         filePicker.init(window, aMenuItem.getAttribute("title"), filePicker.modeSave);
  226.         filePicker.appendFilter("SQLite", "*.sqlite");
  227.         var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
  228.         filePicker.displayDirectory = dirSvc.get("Desk", Ci.nsILocalFile);
  229.         var date = new Date().toLocaleFormat("%Y-%m-%d");
  230.         filePicker.defaultString = dbConn.databaseFile.leafName.replace(".", "-" + date + ".");
  231.         if (filePicker.show() == filePicker.returnCancel || !filePicker.file)
  232.             return;
  233.         var file = filePicker.file.QueryInterface(Ci.nsILocalFile);
  234.         this._gestureSvc.backupMappings(file);
  235.     },
  236.  
  237.     restoreMappings: function(aMenuItem) {
  238.         var filePicker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
  239.         filePicker.init(window, aMenuItem.getAttribute("title"), filePicker.modeOpen);
  240.         filePicker.appendFilter("SQLite", "*.sqlite");
  241.         if (filePicker.show() == filePicker.returnCancel || !filePicker.file)
  242.             return;
  243.         if (!this.promptSvc.confirm(window, "FireGestures", aMenuItem.getAttribute("alerttext")))
  244.             return;
  245.         var file = filePicker.file.QueryInterface(Ci.nsILocalFile);
  246.         this._gestureSvc.restoreMappings(file);
  247.     },
  248.  
  249.     handleTreeEvent: function(event) {
  250.         if (event.type == "dblclick") {
  251.             if (event.target.localName == "treechildren")
  252.             this.doCommand("cmd_edit_gesture");
  253.         }
  254.         else if (event.type == "keypress") {
  255.             switch (event.keyCode) {
  256.                 case event.DOM_VK_RETURN: 
  257.                     this.doCommand("cmd_edit_gesture");
  258.                     break;
  259.                 case event.DOM_VK_DELETE: 
  260.                     this.doCommand("cmd_clear_gesture");
  261.                     break;
  262.                 default: return;
  263.             }
  264.             event.preventDefault();
  265.         }
  266.     },
  267.  
  268.     updateCommands: function() {
  269.         var idxs = gMappingView.getSelectedIndexes();
  270.         var canEdit = idxs.length > 0;
  271.         var canDelete = false, canClear = false;
  272.         idxs.forEach(function(idx) {
  273.             if (gMappingArray[idx][kTypeCol] == TYPE_SCRIPT)
  274.                 canDelete = true;
  275.             if (gMappingArray[idx][kDirectionCol])
  276.                 canClear = true;
  277.         });
  278.         var setElementDisabledByID = function(aID, aDisable) {
  279.             if (aDisable)
  280.                 document.getElementById(aID).removeAttribute("disabled");
  281.             else
  282.                 document.getElementById(aID).setAttribute("disabled", "true");
  283.         };
  284.         setElementDisabledByID("cmd_edit_gesture",  canEdit);
  285.         setElementDisabledByID("cmd_clear_gesture", canClear);
  286.         setElementDisabledByID("cmd_delete_script", canDelete);
  287.     },
  288.  
  289.     doCommand: function(aCommand) {
  290.         switch (aCommand) {
  291.             case "cmd_add_script": 
  292.                 var suggestedName = document.getElementById("bundleMain").getString("NEW_SCRIPT");
  293.                 var nums = [0];
  294.                 gMappingArray.forEach(function(item) {
  295.                     if (item[kNameCol].indexOf(suggestedName) == 0 && /\s\((\d+)\)$/.test(item[kNameCol]))
  296.                         nums.push(parseInt(RegExp.$1, 10));
  297.                 });
  298.                 suggestedName += " (" + (Math.max.apply(this, nums) + 1) + ")";
  299.                 var newIdx = gMappingView.appendItem([TYPE_SCRIPT, suggestedName, "", ""]);
  300.                 this.editGesture(newIdx, true);
  301.                 break;
  302.             case "cmd_edit_gesture" : 
  303.                 var idxs = gMappingView.getSelectedIndexes();
  304.                 idxs.forEach(function(idx) { this.editGesture(idx, false); }, this);
  305.                 break;
  306.             case "cmd_clear_gesture": 
  307.                 var idxs = gMappingView.getSelectedIndexes();
  308.                 idxs.forEach(function(idx) { gMappingArray[idx][kDirectionCol] = ""; });
  309.                 gMappingView.update();
  310.                 break;
  311.             case "cmd_delete_script": 
  312.                 var idxs = gMappingView.getSelectedIndexes();
  313.                 for (var i = idxs.length - 1; i >= 0; i--) {
  314.                     if (gMappingArray[idxs[i]][kTypeCol] == TYPE_SCRIPT)
  315.                         gMappingView.removeItemAt(idxs[i]);
  316.                 }
  317.                 this.rebuildExtraMenus1();
  318.                 break;
  319.         }
  320.         this.updateCommands();
  321.         gShouldCommit = true;
  322.     },
  323.  
  324.     editGesture: function(aIdx, aIsNewScript) {
  325.         var oldCommand   = gMappingArray[aIdx][kCommandCol];
  326.         var oldDirection = gMappingArray[aIdx][kDirectionCol];
  327.         var ret = {
  328.             type     : gMappingArray[aIdx][kTypeCol],
  329.             name     : gMappingArray[aIdx][kNameCol],
  330.             command  : oldCommand,
  331.             direction: oldDirection,
  332.             accepted : false
  333.         };
  334.         var features = "chrome,modal" + (ret.type == TYPE_SCRIPT ? ",all,resizable" : "");
  335.         document.documentElement.openSubDialog("chrome://firegestures/content/edit.xul", features, ret);
  336.         if (!ret.accepted) {
  337.             if (aIsNewScript)
  338.                 gMappingView.removeItemAt(aIdx);
  339.             return;
  340.         }
  341.         if (this.checkConflict(ret.direction, aIdx)) {
  342.             if (aIsNewScript)
  343.                 ret.direction = "";
  344.             else if (oldCommand != ret.command)
  345.                 ret.direction = oldDirection;
  346.             else
  347.                 return;
  348.         }
  349.         gMappingArray[aIdx][kDirectionCol] = ret.direction;
  350.         if (ret.type == TYPE_SCRIPT) {
  351.             gMappingArray[aIdx][kNameCol]    = ret.name;
  352.             gMappingArray[aIdx][kCommandCol] = ret.command;
  353.         }
  354.         this.rebuildExtraMenus1();
  355.         gMappingView.update();
  356.     },
  357.  
  358.     checkConflict: function(aDirection, aIdx) {
  359.         if (!aDirection)
  360.             return false;
  361.         for (var i = 0; i < gMappingArray.length; i++) {
  362.             var item = gMappingArray[i];
  363.             if (i != aIdx && item[kDirectionCol] == aDirection) {
  364.                 var msg = document.getElementById("bundleMain").getFormattedString(
  365.                     "CONFIRM_CONFLICT",
  366.                     [aDirection, item[kNameCol], item[kNameCol]]
  367.                 );
  368.                 var ret = this.promptSvc.confirmEx(
  369.                     window, "FireGestures", msg, this.promptSvc.STD_YES_NO_BUTTONS,
  370.                     null, null, null, null, {}
  371.                 );
  372.                 if (ret == 1)
  373.                     return true;
  374.                 item[kDirectionCol] = "";
  375.                 return false;
  376.             }
  377.         }
  378.         return false;
  379.     },
  380.  
  381.     openURL: function(aURL) {
  382.         var win = Cc["@mozilla.org/appshell/window-mediator;1"]
  383.                   .getService(Ci.nsIWindowMediator)
  384.                   .getMostRecentWindow("navigator:browser");
  385.         if (win)
  386.             win.gBrowser.loadOneTab(aURL, null, null, null, false, false);
  387.         else
  388.             window.open(aURL);
  389.     }
  390.  
  391. };
  392.  
  393.  
  394.  
  395. var gDragDropObserver = {
  396.  
  397.  
  398.     onDragStart: function(event, aXferData, aDragAction) {
  399.         var selIdxs = gMappingView.getSelectedIndexes();
  400.         if (selIdxs.length != 1)
  401.             return;
  402.         var sourceIndex = selIdxs[0];
  403.         if (gMappingArray[sourceIndex][kTypeCol] != TYPE_SCRIPT)
  404.             return;
  405.         aXferData.data = new TransferData();
  406.         aXferData.data.addDataForFlavour(DRAGDROP_FLAVOR, sourceIndex);
  407.         aDragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_MOVE;
  408.     },
  409.  
  410.  
  411.     _flavourSet: null,
  412.  
  413.     getSupportedFlavours: function() {
  414.         if (!this._flavourSet) {
  415.             this._flavourSet = new FlavourSet();
  416.             this._flavourSet.appendFlavour("text/x-moz-url");
  417.         }
  418.         return this._flavourSet;
  419.     },
  420.     canDrop: function(event, aDragSession) { return true; },
  421.     onDragEnter: function(event, aDragSession) {},
  422.     onDragOver: function(event, aFlavour, aDragSession) {},
  423.     onDragExit: function(event, aDragSession) {},
  424.     onDrop: function(event, aXferData, aDragSession) {
  425.         const URL_PREFIX = "data:text/javascript,";
  426.         var lines = aXferData.data.toString().split("\n");
  427.         if (lines.length != 2 || lines[0].indexOf(URL_PREFIX) != 0)
  428.             return;
  429.         lines[0] = decodeURIComponent(lines[0].substr(URL_PREFIX.length));
  430.         gMappingView.appendItem([TYPE_SCRIPT, lines[1], lines[0], ""]);
  431.         PrefsUI.rebuildExtraMenus1();
  432.         gShouldCommit = true;
  433.     },
  434.  
  435. };
  436.  
  437.  
  438.  
  439. function CustomTreeView() {}
  440.  
  441. CustomTreeView.prototype = {
  442.  
  443.  
  444.     get ATOM_SVC() {
  445.         if (!this._atomSvc)
  446.             this._atomSvc = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomService);
  447.         return this._atomSvc;
  448.     },
  449.     _atomSvc: null,
  450.  
  451.     _treeBoxObject: null,
  452.  
  453.  
  454.     appendItem: function(aItem) {
  455.         gMappingArray.push(aItem);
  456.         var newIdx = this.rowCount - 1;
  457.         this._treeBoxObject.rowCountChanged(newIdx, 1);
  458.         this.selection.select(newIdx);
  459.         this._treeBoxObject.ensureRowIsVisible(newIdx);
  460.         this._treeBoxObject.treeBody.focus();
  461.         return newIdx;
  462.     },
  463.  
  464.     removeItemAt: function(aIndex) {
  465.         gMappingArray.splice(aIndex, 1);
  466.         this._treeBoxObject.rowCountChanged(aIndex, -1);
  467.     },
  468.  
  469.     moveItem: function(aSourceIndex, aTargetIndex) {
  470.         var removedItems = gMappingArray.splice(aSourceIndex, 1);
  471.         gMappingArray.splice(aTargetIndex, 0, removedItems[0]);
  472.         gShouldCommit = true;
  473.     },
  474.  
  475.     update: function() {
  476.         this._treeBoxObject.invalidate();
  477.     },
  478.  
  479.     getSelectedIndexes: function() {
  480.         var ret = [];
  481.         var sel = this.selection;
  482.         for (var rc = 0; rc < sel.getRangeCount(); rc++) {
  483.             var start = {}, end = {};
  484.             sel.getRangeAt(rc, start, end);
  485.             for (var idx = start.value; idx <= end.value; idx++) {
  486.                 if (!this.isSeparator(idx))
  487.                     ret.push(idx);
  488.             }
  489.         }
  490.         return ret;
  491.     },
  492.  
  493.     getSourceIndexFromDrag: function() {
  494.         var dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(Ci.nsIDragService);
  495.         var dragSession = dragService.getCurrentSession();
  496.         var xferData = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
  497.         xferData.addDataFlavor(DRAGDROP_FLAVOR);
  498.         dragSession.getData(xferData, 0);
  499.         var obj = {}, len = {};
  500.         var sourceIndex = -1;
  501.         try {
  502.             xferData.getAnyTransferData({}, obj, len);
  503.         }
  504.         catch (ex) {}
  505.         if (obj.value) {
  506.             sourceIndex = obj.value.QueryInterface(Ci.nsISupportsString).data;
  507.             sourceIndex = parseInt(sourceIndex.substring(0, len.value), 10);
  508.         }
  509.         return sourceIndex;
  510.     },
  511.  
  512.  
  513.     get rowCount() {
  514.         return gMappingArray.length;
  515.     },
  516.     selection: null,
  517.     getRowProperties: function(index, properties) {},
  518.     getCellProperties: function(row, col, properties) {
  519.         if (col.index == 0 && this.isSeparator(row))
  520.             properties.AppendElement(this.ATOM_SVC.getAtom("category"));
  521.     },
  522.     getColumnProperties: function(col, properties) {},
  523.     isContainer: function(index) { return false; },
  524.     isContainerOpen: function(index) { return false; },
  525.     isContainerEmpty: function(index) { return false; },
  526.     isSeparator: function(index) {
  527.         return gMappingArray[index][kTypeCol] == TYPE_CATEGORY;
  528.     },
  529.     isSorted: function() { return false; },
  530.     canDrop: function(targetIndex, orientation) {
  531.         var sourceIndex = this.getSourceIndexFromDrag();
  532.         return (
  533.             gMappingArray[targetIndex][kTypeCol] == TYPE_SCRIPT && 
  534.             sourceIndex != -1 && 
  535.             sourceIndex != targetIndex && 
  536.             sourceIndex != (targetIndex + orientation)
  537.         );
  538.     },
  539.     drop: function(targetIndex, orientation) {
  540.         var sourceIndex = this.getSourceIndexFromDrag();
  541.         if (sourceIndex == -1)
  542.             return;
  543.         if (sourceIndex < targetIndex) {
  544.             if (orientation == Ci.nsITreeView.DROP_BEFORE)
  545.                 targetIndex--;
  546.         }
  547.         else {
  548.             if (orientation == Ci.nsITreeView.DROP_AFTER)
  549.                 targetIndex++;
  550.         }
  551.         this.moveItem(sourceIndex, targetIndex);
  552.         this.update();
  553.         this.selection.clearSelection();
  554.         this.selection.select(targetIndex);
  555.     },
  556.     getParentIndex: function(rowIndex) { return -1; },
  557.     hasNextSibling: function(rowIndex, afterIndex) { return false; },
  558.     getLevel: function(index) { return 0; },
  559.     getImageSrc: function(row, col) {},
  560.     getProgressMode: function(row, col) {},
  561.     getCellValue: function(row, col) {},
  562.     getCellText: function(row, col) {
  563.         switch (col.index) {
  564.             case 0: return gMappingArray[row][kNameCol];
  565.             case 1: return gMappingArray[row][kCommandCol].replace(/\r|\n|\t/g, " ");
  566.             case 2: return gMappingArray[row][kDirectionCol];
  567.         }
  568.     },
  569.     setTree: function(tree) {
  570.         this._treeBoxObject = tree;
  571.     },
  572.     toggleOpenState: function(index) {},
  573.     cycleHeader: function(col) {},
  574.     selectionChanged: function() {},
  575.     cycleCell: function(row, col) {},
  576.     isEditable: function(row, col) { return false; },
  577.     isSelectable: function(row, col) {},
  578.     setCellValue: function(row, col, value) {},
  579.     setCellText: function(row, col, value) {
  580.         if (col.index == 0)
  581.             gMappingArray[row][kNameCol] = value;
  582.         else if (col.index == 1)
  583.             gMappingArray[row][kCommandCol] = value;
  584.         else if (col.index == 2)
  585.             gMappingArray[row][kDirectionCol] = value;
  586.     },
  587.     performAction: function(action) {},
  588.     performActionOnRow: function(action, row) {},
  589.     performActionOnCell: function(action, row, col) {},
  590.  
  591. };
  592.  
  593.  
  594.